﻿package zf.data.math
{
	/**
	 * 不重复的数组数据池。在设定的数据池中，获取不重复的数据。获取一个数据，数据池将减少一个。
	 * @author mike.zhang
	 * @langversion 3.0 
	 * @playerversion Flash 9 
	 * 
	 */
	public class Notecho
	{
		private var _data:Array;
		private var pool:Array;
		private var _cyc:Boolean=false;
		private var _length:uint;

		/**
		 * 不重复的数组数据池 
		 * @param args 要添加到数据池中的数据
		 * 
		 */
		public function Notecho (... args)
		{
			pool=new Array  ;
			_data=new Array  ;
			_length=0;
			if (args.length > 0)
			{
				append.apply (this,args);
			}
		}
		/**
		 * 数据池中数据，其类型是数组，你也可以通过 append() 方法来给数据池中添加数据 
		 * @return 数组
		 * @see #append()
		 */
		public function get data ():Array
		{
			return _data;
		}

		public function set data (v:Array):void
		{
			_data=v;
			cratePool ();
		}
		/**
		 * 是否循环取数据，默认为flase，不循环。如果设置为true，在数据池中数据被取完后，将用原来的数据重新填充数据池，使其可以继续取出数据。如果设置为false,数据池中的数据全部取完后将为null
		 * @return Boolean
		 * 
		 */
		public function get cyc ():Boolean
		{
			return _cyc;
		}

		public function set cyc (v:Boolean):void
		{
			_cyc=v;
		}
		/**
		 * 向数据池中添加数据 
		 * @param args 要往数据池中添加的数据
		 * 
		 */
		public function append (... args):void
		{
			var l:uint=args.length;
			var k:uint=_data.length;
			for (var i:uint=0; i < l; i++)
			{
				_data.push (args[i]);
				pool.push (k + i);
			}
			_length+= l;
		}
		/**
		 * 创建索引数组 
		 * 
		 */
		private function cratePool ():void
		{

			_length=_data.length;
			pool=new Array;
			for (var i:uint=0; i < _length; i++)
			{
				pool[i]=i;
			}
		}
		/**
		 * 随机取出一个数据。如果数据池中有数据，则随机取出一个数据并返回；如果数据池已经为空，且 cyc 为false,则返回 null， 若 cyc 为true，那么数据池将被重新填充
		 * @return 数据或null
		 * 
		 */
		public function popRandomData ():*
		{
			if (_length == 0)
			{
				if (cyc)
				{
					cratePool ();
				}
				else
				{
					return null;
				}
			}
			var index:uint=Math.floor(Math.random() * _length * 10) % _length;
			var k:uint=pool[index];
			pool[index]=pool[_length - 1];
			pool.pop ();
			_length--;
			return _data[k];
		}
		/**
		 * 取出数据池中下标为 index 的数据，如果 index 大于数据池中数据个数，那么将返回数据池中下标最大的数据 
		 * @param index 要获取数据的下标
		 * @return 数据或null
		 * 
		 */
		public function popIndexData (index:uint=0):*
		{
			if (_length == 0)
			{
				return null;
			}
			if (index > _length)
			{
				index=_length;
			}
			var k:uint=pool[index];
			pool[index]=pool[_length - 1];
			pool.pop ();
			_length--;
			return _data[k];
		}
		/**
		 * 获取数据池中当前数据的个数 
		 * @return 数据个数
		 * 
		 */
		public function get length ():uint
		{
			return _length;
		}
	}
}